package cn.owng.cli.db;

import cn.owng.cli.Env;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.JavaMigration;
import org.reflections.Reflections;
import picocli.CommandLine;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;

/**
 * 微信公众号请关注: 开源螺丝钉
 * <br>
 * 码云请关注: <a href="https://gitee.com/xiyoufang">https://gitee.com/xiyoufang</a>
 * <br>
 * 哔哩哔哩请关注: <a href="https://space.bilibili.com/438927834">https://space.bilibili.com/438927834</a>
 *
 * @author xiyoufang
 */
@CommandLine.Command(name = "migrate", description = "迁移数据库")
@Slf4j
public class Migrate implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        Env.Db db = Env.db();
        try (HikariDataSource ds = new HikariDataSource()) {
            ds.setJdbcUrl(String.format("%s/%s?%s", db.getUrl(), db.getDatabase(), db.getQuery()));
            ds.setUsername(db.getUsername());
            ds.setPassword(db.getPassword());
            Flyway flyway = Flyway.configure().locations("db/migration")
                    .javaMigrations(getJavaMigrations("db.migration"))
                    .table("flyway_migrate")
                    .baselineOnMigrate(true)
                    .dataSource(ds.getJdbcUrl(), ds.getUsername(), ds.getPassword())
                    .load();
            flyway.migrate();
        }
        return 0;
    }

    private JavaMigration[] getJavaMigrations(String... packageNames) throws Exception {
        Set<JavaMigration> javaMigrations = new HashSet<>();
        for (String packageName : packageNames) {
            Reflections reflections = new Reflections(packageName);
            Set<Class<? extends BaseJavaMigration>> subTypes = reflections.getSubTypesOf(BaseJavaMigration.class);
            for (Class<? extends BaseJavaMigration> subType : subTypes) {
                javaMigrations.add(subType.getDeclaredConstructor().newInstance());
            }
        }
        return javaMigrations.toArray(new JavaMigration[]{});
    }
}
